package cc.shacocloud.mirage.restful;

import cc.shacocloud.mirage.utils.comparator.Ordered;
import io.vertx.core.Future;
import io.vertx.core.http.HttpHeaders;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

/**
 * {@link HandlerExceptionResolver}实现的抽象基类并实现{@link Ordered}接口
 * <p>
 * 默认为{@link #getOrder()}
 */
@Slf4j
public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered {
    
    private boolean preventResponseCaching = false;
    
    @Override
    public Future<Object> resolveException(HttpRequest request, HttpResponse response,
                                           VertxInvokeHandler handler, Throwable cause) {
        if (shouldApplyTo(request, handler)) {
            prepareResponse(cause, response);
            
            return doResolveException(request, response, handler, cause);
        }
        
        // 返回空的结果表示异常处理器不支持解析
        return Future.succeededFuture(SKIP);
    }
    
    /**
     * 检查这个解析器是否应该应用于给定的处理程序。
     * <p>
     * 这里永远返回 {@code ture}，子类可以自行实现
     */
    protected boolean shouldApplyTo(@NotNull HttpRequest request, @NotNull VertxInvokeHandler handler) {
        return true;
    }
    
    /**
     * 为处理给定请求期间发生的给定异常构建日志消息
     *
     * @return 要使用的日志消息
     */
    protected String buildLogMessage(Throwable ex, HttpRequest request) {
        return "解析异常： [" + ex + "]";
    }
    
    /**
     * 为异常情况准备响应。
     * <p>
     * 默认实现阻止响应被缓存，如果{@link #setPreventResponseCaching} 属性被设置为"true"。
     *
     * @param cause    在处理程序执行期间抛出的异常
     * @param response 当前的HTTP响应
     * @see #preventCaching
     */
    protected void prepareResponse(Throwable cause, HttpResponse response) {
        if (this.preventResponseCaching) {
            preventCaching(response);
        }
    }
    
    /**
     * 通过设置相应的 HTTP {@code Cache-Control: no-store} 头阻止响应被缓存。
     *
     * @param response 当前的HTTP响应
     */
    protected void preventCaching(@NotNull HttpResponse response) {
        response.headers().add(HttpHeaders.CACHE_CONTROL, "no-store");
    }
    
    
    /**
     * 指定是否阻止此异常解析器解析的任何视图的HTTP响应缓存。
     * <p>
     * 默认值是{@code false}。将其切换为{@code true}，以自动生成HTTP响应头以抑制响应缓存
     */
    public void setPreventResponseCaching(boolean preventResponseCaching) {
        this.preventResponseCaching = preventResponseCaching;
    }
    
    
    /**
     * 实际解决在处理程序执行期间抛出的给定异常
     */
    protected abstract Future<Object> doResolveException(@NotNull HttpRequest request,
                                                         @NotNull HttpResponse response,
                                                         @NotNull VertxInvokeHandler handler,
                                                         @NotNull Throwable cause);
    
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
